import React, { Component } from "react";
let hooksStates = [];
let hookIndex = 0;

// 维护一个hooks的状态数组
// 和一个指针
// 每个hooks对应一个指针，指针和状态数组一一对应
// 这样顺序才不会有问题

/**
 *
 * @param {*} initState [fn/any]
 */
export function useState(initState) {
  initState = typeof initState === "function" ? initState() : initState;
  hooksStates[hookIndex] = hooksStates[hookIndex] || initState;
  // 保存当前的指针
  // 不然下次再次调用useState，指针会改变
  let currentIndex = hookIndex;
  // newState [fn/any]
  function setState(newState) {
    if (typeof newState === "function") {
      newState = newState(hooksStates[currentIndex]);
    }
    hooksStates[currentIndex] = newState;
    // scheduleUpdate()
    return hooksStates[currentIndex];
  }
  return [
    // 移动指针，需要与状态一一对应
    hooksStates[hookIndex++],
    setState,
  ];
  // return useReducer(null, initState)
}

// 兼容两个api
export function useReducer(reducer, initState) {
  initState = typeof initState === "function" ? initState() : initState;
  hooksStates[hookIndex] = hooksStates[hookIndex] || initState;
  let currentIndex = hookIndex;
  function dispatch(action) {
    // reducer(hooksStates[currentIndex], action)
    // 传递状态和更改状态的action
    let newState = reducer
      ? reducer(hooksStates[currentIndex], action)
      : action;
    if (typeof newState === "function") {
      newState = newState(hooksStates[currentIndex]);
    }
    return (hooksStates[currentIndex] = newState);
  }
  return [hooksStates[hookIndex++], dispatch];
}

// 函数缓存
export function useMemo(factory, deps) {
  // 第二次执行，先判断老的依赖和传入的依赖是否相同
  if (hooksStates[hookIndex]) {
    const [lastMemo, lastDeps] = hooksStates[hookIndex];
    const same = deps.every((item, index) => {
      return item === lastDeps[index];
    });
    // 相同则取缓存中的值
    if (same) {
      hookIndex++;
      return lastMemo;
    } else {
      // 不相同则调用函数，返回最新的值
      let newMemo = factory();
      hooksStates[hookIndex++] = [newMemo, deps];
      return newMemo;
    }
  } else {
    // 第一次执行
    let newMemo = factory();
    hooksStates[hookIndex++] = [newMemo, deps];
    return newMemo;
  }
}

export function useCallback(callback, deps) {
  if (hooksStates[hookIndex]) {
    const [lastCallback, lastDeps] = hooksStates[hookIndex];
    const same = deps.every((item, index) => {
      return item === lastDeps[index];
    });
    if (same) {
      hookIndex++;
      return lastCallback;
    } else {
      hooksStates[hookIndex++] = [callback, deps];
      return callback;
    }
  } else {
    hooksStates[hookIndex++] = [callback, deps];
    return callback;
  }
}

export function createContext(initialValue = {}) {
  let context = { Provider, Consumer };
  function Provider(props) {
    // 获取状态
    context._currentValue = context._currentValue || initialValue;
    // 合并状态
    Object.assign(context._currentValue, props.value);
    // 返回子元素
    return props.children;
  }
  function Consumer(props) {
    // 调用子元素，传入状态
    return props.children(context._currentValue);
  }
}

export function useContext(context) {
  return context._currentValue;
}

export function useEffect(callback, deps) {
  // debugger
  if (hooksStates[hookIndex]) {
    const [destoryFunction, lastDeps] = hooksStates[hookIndex];
    const same =
      deps &&
      deps.every((item, index) => {
        return item === lastDeps[index];
      });
    if (same) {
      hookIndex++;
    } else {
      // 销毁
      destoryFunction && destoryFunction();
      // 将函数放在宏任务队列中
      setTimeout(() => {
        let destoryFunction = callback();
        hooksStates[hookIndex++] = [destoryFunction, deps];
      });
    }
  } else {
    setTimeout(() => {
      let destoryFunction = callback(); // 调用回调，返回一个销毁的函数
      hooksStates[hookIndex++] = [destoryFunction, deps];
    });
  }
}

export function useLayoutffect(callback, deps) {
  // debugger
  if (hooksStates[hookIndex]) {
    const [destoryFunction, lastDeps] = hooksStates[hookIndex];
    const same =
      deps &&
      deps.every((item, index) => {
        return item === lastDeps[index];
      });
    if (same) {
      hookIndex++;
    } else {
      // 销毁
      destoryFunction && destoryFunction();
      // 将函数放在微任务队列中
      queueMicrotask(() => {
        let destoryFunction = callback();
        hooksStates[hookIndex++] = [destoryFunction, deps];
      });
    }
  } else {
    setTimeout(() => {
      let destoryFunction = callback(); // 调用回调，返回一个销毁的函数
      hooksStates[hookIndex++] = [destoryFunction, deps];
    });
  }
}

export function useRef(initialValue) {
  hooksStates[hookIndex] = hooksStates[hookIndex] || { current: initialValue };
  return hooksStates[hookIndex++];
}

export function createRef() {
  return {
    current: null,
  };
}

export function usewardRef(FunctionComponent) {
  class x extends Component {
    render() {
      if (FunctionComponent.length < 2) {
        console.warn("");
      }
      return FunctionComponent(this.props, this.ref);
    }
  }
  return x;
}
